CloudFormation で BlockDeviceMapping プロパティを利用している EBS のサイズ拡張を行う方法を教えてください
困っていること
CloudFormation テンプレートの BlockDeviceMappings プロパティを利用して EC2 のルートボリュームに紐づく EBS の設定を実施しています。ディスク拡張を実施するために VolumeSize の値を変更してテンプレートをデプロイしたところ、当該 EC2 のインスタンス再作成が発生してしまいました。
EC2 のインスタンス再作成を伴わずに CloudFormation でボリュームサイズの拡張を行うにはどうすれば良いでしょうか?
どう対応すればいいの?
2024/11/25 現在の仕様として、BlockDeviceMappings プロパティの VolumeSize の値を変更した場合、紐づいている EC2 インスタンスの再作成は避けられません。
以下の CloudFormation の Github においても関連する issue が open になっていることが確認できます。
マネジメントコンソールや CLI から直接ボリュームサイズを変更した場合には EC2 の再作成は発生しないため、手動で当該操作を実施するというのが対応策です。
しかしながら、手動変更を行ってしまうとテンプレートの内容と実リソースの設定に乖離が発生し、ドリフトが検出されるようになってしまうため、CloudFormation でのリソース管理を継続したい場合は、以下の 3 ステップを踏む必要があります。
- 当該の EC2 インスタンスを一時的に CloudFormation スタックの管理下から外す
- 手動で EBS のサイズを変更
- 当該の EC2 インスタンスを再度 CloudFormation スタックにインポートする
やってみた
以下の CloudFormation テンプレートを利用し、実際に上記の 1~3 の手順を実施してみたいと思います。
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Create EC2'
#----------------------------------------------
# Parameters Section
#----------------------------------------------
Parameters:
InstanceType:
Description: EC2 instance type
Type: String
Default: t3.micro
InstanceAMI:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64
RootVolumeSize:
Description: Size of root volume in GB
Type: Number
Default: 16
#----------------------------------------------
# Resources Section
#----------------------------------------------
Resources:
# VPC
Vpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: Vpc
# Internet Gateway
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: InternetGateway
VpcGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref InternetGateway
# Public Subnet
PublicSubnet01:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref Vpc
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: PublicSubnet01
# Route Table
RouteTable01:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref Vpc
Tags:
- Key: Name
Value: RouteTable01
Route01:
Type: AWS::EC2::Route
DependsOn: VpcGatewayAttachment
Properties:
RouteTableId: !Ref RouteTable01
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableAssociation01:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet01
RouteTableId: !Ref RouteTable01
# Security Group
SecurityGroup01:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow SSH access
VpcId: !Ref Vpc
# EC2 Instance
Instance01:
Type: AWS::EC2::Instance
DeletionPolicy: Retain
Properties:
InstanceType: !Ref InstanceType
ImageId: !Ref InstanceAMI
SubnetId: !Ref PublicSubnet01
SecurityGroupIds:
- !Ref SecurityGroup01
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: !Ref RootVolumeSize
VolumeType: gp3
DeleteOnTermination: true
Tags:
- Key: Name
Value: Instance01
#----------------------------------------------
# Outputs Section
#----------------------------------------------
EC2 インスタンスを一時的に CloudFormation スタックの管理下から外す
上記のテンプレートを実行し、スタックの作成が完了したところから作業をはじめていきます。
まず、リソースを CloudFormation スタックの管理から外すために、BlockDeviceMappings プロパティを利用している当該の EC2 (Instance01) に関する記載をコメントアウトしたテンプレートファイルを別に用意します。
# Instance01:
# Type: AWS::EC2::Instance
# DeletionPolicy: Retain
# Properties:
# InstanceType: !Ref InstanceType
# ImageId: !Ref InstanceAMI
# SubnetId: !Ref PublicSubnet01
# SecurityGroupIds:
# - !Ref SecurityGroup01
# BlockDeviceMappings:
# - DeviceName: /dev/xvda
# Ebs:
# VolumeSize: !Ref RootVolumeSize
# VolumeType: gp3
# DeleteOnTermination: true
# Tags:
# - Key: Name
# Value: Instance01
CloudFormation コンソールで当該スタックを選択し、「更新」をクリックします。
「既存のテンプレートを置換」を選択し、コメントアウト後のテンプレートファイルをアップロードします。
実行前に変更セットを参照し、更新時に当該の EC2 リソースが削除されてしまわないよう、ポリシーアクションが "Retain" になっていることを確認したらテンプレートを実行します。
更新が完了し、EC2 がスタックの管理化から外れたことが確認できました。
手動で EBS のサイズを変更
次に、手動で EBS のサイズを変更します。
マネジメントコンソールで当該の EBS を選択し、ボリュームの変更を選択します。
サイズの値を 8 から 16 に変更し、「変更」をクリックし、確認画面で改めて「変更」を選択すれば変更完了です。
なお、当記事の主旨からは外れるため詳細は割愛しますが、EBS ボリュームのサイズ変更後は OS 上でもファイルシステムの拡張作業を実施する必要があるのでご注意ください。[1]
EC2 インスタンスを再度 CloudFormation スタックにインポート
EBS のサイズ変更が完了したので、EC2 を再び CloudFormation スタックにインポートしていきたいと思います。[2]
RootVolumeSize を手動変更後の値である 16 に指定し、EC2 リソースのコメントアウトを解除したテンプレートファイルを改めて事前に用意しておきます。
RootVolumeSize:
Description: Size of root volume in GB
Type: Number
Default: 16
<中略>
Instance01:
Type: AWS::EC2::Instance
DeletionPolicy: Retain
Properties:
InstanceType: !Ref InstanceType
ImageId: !Ref InstanceAMI
SubnetId: !Ref PublicSubnet01
SecurityGroupIds:
- !Ref SecurityGroup01
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: !Ref RootVolumeSize
VolumeType: gp3
DeleteOnTermination: true
Tags:
- Key: Name
Value: Instance01
CloudFormation コンソールで当該スタックを選択し、「スタックの更新」→「既存のリソースを使用(リソースをインポート)」をクリックします。
記載の前提条件を確認したら「次へ」をクリックします。
変更後のテンプレートをアップロードします。
「インポートするリソース」の画面が表示されたら、当該 EC2 の InstanceId を入力します。
RootVolumeSize が 16 になっていることを確認します。
更新内容を確認したら「リソースをインポート」を実行します。
実行後、ステータスが "IMPORT_COMPLETE" になり、当該 EC2 が再び CloudFormation スタックの管理化に置かれたことが確認できました。
以上で CloudFormation スタックへのインポートは完了になります。
終わりに
CloudFormation での管理を継続しながら、BlockDeviceMappings プロパティを利用した EBS のサイズ拡張を行うための方法を紹介しました。
手順自体は複雑ではないですが、リソースのインポート作業などの一手間を挟む必要がありますので、同作業を予定する際は事前に検証環境などで流れを確認した上で、実施を検討いただければと思います。